/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package tarea.memoriaintermedia;

import java.util.LinkedList;
import java.util.Queue;
import java.util.logging.Logger;

/**
 *
 * @author Grover
 */
public class GestorMemoriaIntermedia {
    static final Logger logger= Logger.getLogger("Gestion de Buffer");
    /**Representa a los bloques de la memoria intermedia o buffer
     memoria intermedia o buffer*/
    private Pagina[] buffer;
    /**Numero de paginas en total en el buffer.*/
    private int numeroPaginas;
    /**Posicion en el buffer de la ultima pagina colocada.*/
    private int posicionUltimaPagina=-1;
    /**Cola para el cotrol de sustitucion basada en LRU.*/
    private Queue colaLRU;
    
    /**
     * Crea un nuevo Gestor de memoria intermedia.
     * 
     * @param numeroPaginas cantidad de paginas en total en el buffer. 
     */
    public GestorMemoriaIntermedia(int numeroPaginas){
        this.numeroPaginas=numeroPaginas;
        //crear el buffer con paginas vacias
        buffer=new Pagina[numeroPaginas];
        //crear una cola FIFO
        colaLRU = new LinkedList<Integer>();
    }
    
    /**
     * Devuelve una pagina conociendo el numero de la pagina.
     * 
     * @param numeroPagina el id de la pagina que queremos devolver
     * @return la pagina del id de pagina proporcionado.
     */
    public Pagina recuperarPaginaDelBuffer(int numeroPagina,boolean EsClavado){
        if(!EsClavado){
        //verifica si la pagina esta en el buffer
        int posicion=posicionDePaginaEnBuffer(numeroPagina);
        if(posicion>=0){//la pagina esta en el buffer
            //marcar pagina o bloque como recientemente referenciado
            colaLRU.remove(numeroPagina);
            colaLRU.add(numeroPagina);
            //devolver la pagina del buffer al solicitante
            return buffer[posicion];
        }}
        return null;
        
    }
    /**
     * Poner una pagina en el buffer de la memoria intermedia.
     * 
     * @param pagina la pagina a ser insertado en el buffer.
     * @return la pagina que sera descartada del buffer si es necesario.
     */
    public Pagina ponerPaginaEnBuffer(Pagina pagina){
        //si la pagina esta en el buffer
        if(estaPaginaEnBuffer(pagina)){//tarea verificar si se ha modificado
            //no descartar ninguna pagina o bloque
            return null;
        }//si la pagina no esta en el buffer,pero con espacio en el buffer
        else if(!bufferLLeno()){
            //asignar la nueva pagina al bloque o pagina libre del buffer
            posicionUltimaPagina++;
            buffer[posicionUltimaPagina]=pagina;
            //actualizar la LRU
            colaLRU.remove(posicionUltimaPagina);
            colaLRU.add(posicionUltimaPagina);
            return null;
        }//si la pagina no esta en el buffer,pero sin espacio en el buffer
        else{
            //recuperar la pagina a descartarpagina adescartar de la cola LRU
            //identificar el ID 
            int numeroPaginaDescartada=(Integer)colaLRU.remove();
            //conociendo el ID pagina ubicar la posicion de la pagina en el buffer
            //dvuelv la posicion de la pagina descartada
            int posicion=posicionDePaginaEnBuffer(numeroPaginaDescartada);
            //recuperar la pagina a descartar del buffer
            Pagina paginaDescartada=buffer[posicion];
            //actualizar la nueva pagina en la posicion de la pagina descartada
            buffer[posicion]=pagina;
            //hacer que el ID de la nueva pagina sea el mas recientemente referenciado
            colaLRU.add(pagina.getNumeroPagina());
            return paginaDescartada;
        }
    }
    private int posicionDePaginaEnBuffer(int numeroPagina){
        int posicion=-1;
        for (int i = 0; i < buffer.length; i++) {
            if(buffer[i]!=null && numeroPagina==buffer[i].getNumeroPagina()){
                posicion=i;
                break;
            }
        }
        return posicion;
    }
    private boolean estaPaginaEnBuffer(Pagina pagina){
        return (posicionDePaginaEnBuffer(pagina.getNumeroPagina())!=-1);
    }
    private boolean bufferLLeno(){
        return numeroPaginas-1==posicionUltimaPagina;
    }
    @Override
    public  String toString(){
        String resultado="";
        for (int i = 0; i < buffer.length; i++) {
            resultado+="Pagina["+i+"]:"+buffer[i]+"\n";
        }
        return resultado+"\n"+this.colaLRU;
    }
    public static void main(String[] args){
        //crear un gestor de memoria
        GestorMemoriaIntermedia gestorBuffer=new GestorMemoriaIntermedia(6);
        //paginas del disco
        System.out.println("Paginas del Disco :");
        Pagina[] paginas=new Pagina[10];
        for (int i = 0; i < paginas.length; i++) {
            Pagina pagina=new Pagina(i,"p"+i);
            paginas[i]=pagina;
            System.out.println(pagina);
        }
        System.out.println("Contenido del Gestor :");
        System.out.println(gestorBuffer);
        
        for (int i = 0; i < paginas.length; i++) {
            gestorBuffer.ponerPaginaEnBuffer(paginas[i]);
        }
        System.out.println("Contenido del Gestor depues de poner bloques :");
        System.out.println(gestorBuffer);
        
        System.out.println("Poner una Pagina al Buffer :");
        Pagina paginaN=new Pagina(10, "p10");
        Pagina paginaE=gestorBuffer.ponerPaginaEnBuffer(paginaN);
        System.out.println(paginaE);
        System.out.println(gestorBuffer);
        
        System.out.println("Recuperar una pagina del Buffer :");
        Pagina pagina1=gestorBuffer.recuperarPaginaDelBuffer(7,false);
        System.out.println(pagina1);
        System.out.println(gestorBuffer);
        
        System.out.println("Recuperar otra pagina del Buffer :");
        Pagina pagina2=gestorBuffer.recuperarPaginaDelBuffer(1,false);
        System.out.println(pagina2);
        System.out.println(gestorBuffer);
    }
}
